import { Repository } from 'typeorm';
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import {
  ERROR_USER_ALREADY_EXISTS,
  ERROR_USER_NOT_EXISTS,
  ERROR_TOKEN_NOT_ENOUGH,
} from '@/common/constant';
import { User, UserStatus } from './entities/user.entity';
import { WechatService } from '../wechat/wechat.service';
import { RegisterUserDto } from './dto/register-user.dto';
import { LoginUserDto } from './dto/login-user.dto';
import { UpdateUserDto } from './dto/update-order.dto';
import { SaveAddressDto } from './dto/save-address.dto';
import { WechatLoginDto } from './dto/wechat-login.dto';

const hasRegisted = (user: User, phone: string, openId: string) => {
  return user.phone === phone && user.openId === openId;
};

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly wechatService: WechatService,
    private readonly jwtService: JwtService,
  ) { }

  findOneByOpenId(openId: string) {
    return this.userRepository.findOneBy({ openId });
  }

  async Detail(id: string): Promise<User> {
    return await this.userRepository.findOneBy({ id });
  }

  async Update(id: string, userUpdateDto: UpdateUserDto) {
    return await this.userRepository.update(id, userUpdateDto);
  }

  async QueryPhoneByPhoneCode(code: string): Promise<string> {
    return await this.wechatService.GetUserPhoneByCode(code);
  }

  async QueryPhoneByLoginCode(code: string): Promise<string> {
    const openId = await this.wechatService.GetUserOpenIdByCode(code);
    const user = await this.userRepository.findOneBy({ openId });
    return user?.phone;
  }

  async RegisterAndLogin(registerUserDto: RegisterUserDto) {
    const openId = await this.wechatService.GetUserOpenIdByCode(
      registerUserDto.code,
    );
    await this.Register(registerUserDto.phone, openId);
    return await this.LoginByOpenId(openId);
  }

  async Register(phone: string, openId: string): Promise<void> {
    const hasUser = await this.userRepository.findOneBy({ openId });
    if (hasUser && hasRegisted(hasUser, phone, openId)) return;
    if (hasUser && hasUser.phone !== phone) {
      throw new InternalServerErrorException(ERROR_USER_ALREADY_EXISTS);
    }
    const user = new User(phone, openId);
    await this.userRepository.save(user);
  }

  async Login(loginUserDto: LoginUserDto) {
    const openId = await this.wechatService.GetUserOpenIdByCode(
      loginUserDto.code,
    );
    return await this.LoginByOpenId(openId);
  }

  async LoginByOpenId(openId: string) {
    const user = await this.userRepository.findOneBy({ openId });
    if (!user) throw new InternalServerErrorException(ERROR_USER_NOT_EXISTS);
    const accessToken = await this.jwtService.signAsync({ ...user });
    return {
      user,
      accessToken,
    };
  }

  async becomeVip(userId: string) {
    const user = await this.userRepository.findOneBy({ id: userId });
    if (!user) throw new InternalServerErrorException(ERROR_USER_NOT_EXISTS);
    user.status = UserStatus.VIP;
    user.invitationCode = user.openId;
    return await this.userRepository.save(user);
  }

  async sendInviteReward(userId: string) {
    const user = await this.userRepository.findOneBy({ id: userId });
    if (!user) throw new InternalServerErrorException(ERROR_USER_NOT_EXISTS);
    user.balance += 50;
    return await this.userRepository.save(user);
  }

  // 保存用户地址
  async saveAddress(params: SaveAddressDto) {
    const user = await this.userRepository.findOneBy({ id: params.userId });
    if (!user) throw new InternalServerErrorException(ERROR_USER_NOT_EXISTS);
    user.fullAddress = params.fullAddress;
    user.community = params.community;
    user.building = params.building;
    user.unit = params.unit;
    user.room = params.room;
    return await this.userRepository.save(user);
  }

  async getUserList() {
    return await this.userRepository.find({
      order: {
        createTime: 'DESC',
      },
    });
  }

  // 微信一键登录
  async wechatLogin(wechatLoginDto: WechatLoginDto) {
    try {
      // 获取用户手机号
      const phone = await this.wechatService.GetUserPhoneByCode(wechatLoginDto.phoneCode);

      // 获取用户openId
      const openId = await this.wechatService.GetUserOpenIdByCode(wechatLoginDto.code);

      // 查找用户是否已存在
      let user = await this.userRepository.findOneBy({ openId });

      if (user) {
        // 用户存在，更新信息
        user.phone = phone;
        user.nickName = wechatLoginDto.nickName;
        user.avatarUrl = wechatLoginDto.avatarUrl;
        await this.userRepository.save(user);
      } else {
        // 用户不存在，注册新用户
        user = new User(phone, openId, wechatLoginDto.nickName, wechatLoginDto.avatarUrl);
        await this.userRepository.save(user);
      }

      // 生成JWT Token
      const accessToken = await this.jwtService.signAsync({ ...user });

      return {
        user,
        accessToken,
      };
    } catch (error) {
      throw new InternalServerErrorException(error.message || '微信登录失败');
    }
  }
}
